home *** CD-ROM | disk | FTP | other *** search
- Subject: v22i047: NN Newsreader, release 6.4, Part12/21
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: ca2064a3 2388034d b708a9ba bb673f97
-
- Submitted-by: "Kim F. Storm" <storm@texas.dk>
- Posting-number: Volume 22, Issue 47
- Archive-name: nn6.4/part12
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: admin.c help/help.read inews/inews.c variable.c
- # Wrapped by storm@texas.dk on Sun May 6 18:19:49 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 12 (of 22)."'
- if test -f 'admin.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'admin.c'\"
- else
- echo shar: Extracting \"'admin.c'\" \(21406 characters\)
- sed "s/^X//" >'admin.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- X *
- X * nnadmin - nn administator program
- X */
- X
- X#include <signal.h>
- X#include <errno.h>
- X#include "config.h"
- X#include "db.h"
- X#include "proto.h"
- X#include "term.h"
- X
- Ximport char
- X *master_directory, *db_directory, *db_data_directory,
- X *bin_directory, *news_directory, *news_lib_directory,
- X *log_file, *news_active, *pager,
- X group_path_name[];
- X
- Ximport char *exec_chdir_to;
- X
- X
- Xstatic char *pre_input;
- Xstatic int verbose = 1;
- X
- Xextern int group_completion();
- X
- X
- Xstatic get_cmd(prompt1, prompt2)
- Xchar *prompt1, *prompt2;
- X{
- X char c;
- X
- X if (s_hangup) {
- X printf("\nnnmaster hangup\n");
- X nn_exit(0);
- X }
- X
- X s_keyboard = 0;
- X
- X if (pre_input) {
- X if ((c = *pre_input++) == NUL)
- X nn_exit(0);
- X } else {
- X do {
- X if (prompt1) printf("\r%s\n", prompt1);
- X if (prompt2) printf("\r%s >>>", prompt2);
- X fl;
- X raw();
- X c = get_c();
- X unset_raw();
- X if (c == K_interrupt)
- X s_keyboard++;
- X else
- X if (c == '!') {
- X putchar(NL);
- X if (exec_chdir_to != NULL)
- X printf("\n\rDirectory: %s", exec_chdir_to);
- X run_shell((char *)NULL, 0);
- X } else
- X printf("%c\n\n\r", c);
- X } while (c == '!');
- X }
- X
- X if (islower(c))
- X c = toupper(c);
- X
- X return c;
- X}
- X
- X
- Xstatic long get_entry(prompt_str, min_val, max_val)
- Xchar *prompt_str;
- Xlong min_val, max_val;
- X{
- X char buf[100];
- X long val;
- X
- X loop:
- X
- X printf("%s %ld..%ld (or all): ", prompt_str, min_val, max_val);
- X fl;
- X gets(buf);
- X if (buf[0] == 'a' || buf[0] == NUL)
- X return -1L;
- X
- X val = atol(buf);
- X if (val < min_val || val > max_val) goto loop;
- X
- X return val;
- X}
- X
- X
- Xstatic admin_confirm(action, must_confirm)
- Xchar *action;
- X{
- X char buffer[100];
- X
- X if (pre_input && !must_confirm) return 1;
- X
- X sprintf(buffer, "Confirm %s Y)es N)o", action);
- X
- X return get_cmd((char *)NULL, buffer) == 'Y';
- X}
- X
- Xstatic char *get_groupname()
- X{
- X char * groupname;
- X
- X raw();
- X printf("\n\n\r");
- X prompt_line = Lines - 2;
- X prompt("Group: ");
- X fl;
- X groupname = get_s(NONE, NONE, NONE, group_completion);
- X unset_raw();
- X
- X putchar(NL); putchar(CR);
- X
- X if (groupname == NULL) return NULL;
- X
- X if (groupname[0]) return groupname;
- X
- X if (current_group == NULL) return NULL;
- X if (current_group->group_flag & G_FOLDER) return NULL;
- X
- X return current_group->group_name;
- X}
- X
- X
- Xstatic update_master()
- X{
- X register group_header *gh;
- X int ngp;
- X
- X if (who_am_i != I_AM_ADMIN) {
- X printf("Can only perform (U)pdate as nnadmin\n");
- X return;
- X }
- X
- X ngp = master.number_of_groups;
- X
- X open_master(OPEN_READ);
- X
- X if (master.number_of_groups != ngp) {
- X printf("\nNumber of groups changed from %d to %d\n",
- X ngp, master.number_of_groups);
- X }
- X
- X ngp = 0;
- X
- X Loop_Groups_Header(gh)
- X if (update_group(gh) == -1) ngp++;
- X
- X if (ngp) printf("There are %d blocked groups\n", ngp);
- X}
- X
- Xstatic find_files(gh)
- Xgroup_header *gh;
- X{
- X char command[512], name[FILENAME], *db_data_path();
- X
- X if (gh == NULL) {
- X if (db_data_directory == NULL) {
- X printf("Cannot list all files (they are scattered over the news partition)\n");
- X return;
- X }
- X sprintf(command, "ls -l %s | %s", db_data_directory, pager);
- X } else
- X sprintf(command, "ls -l %s", db_data_path(name, gh, '*'));
- X system(command);
- X}
- X
- Xstatic master_status()
- X{
- X int cur_group, nblocked, nignored;
- X long articles, disk_use;
- X register group_header *gh;
- X
- X printf("\nMaster:\n");
- X printf(" initialized: %s\n", date_time(master.db_created));
- X printf(" last_scan: %s\n", date_time(master.last_scan));
- X printf(" last_size: %ld\n", (long)master.last_size);
- X printf(" no of groups: %d\n", master.number_of_groups);
- X
- X articles = disk_use = 0;
- X nblocked = nignored = 0;
- X
- X for (cur_group = 0; cur_group < master.number_of_groups; cur_group++) {
- X gh = &active_groups[cur_group];
- X
- X#define DISK_BLOCKS(bytes) (((bytes) + 1023) / 1024)
- X
- X disk_use += DISK_BLOCKS(gh->index_write_offset);
- X disk_use += DISK_BLOCKS(gh->data_write_offset);
- X
- X articles += gh->last_db_article - gh->first_db_article + 1;
- X
- X if (gh->master_flag & M_BLOCKED) nblocked++;
- X if (gh->master_flag & M_IGNORE_GROUP) nignored++;
- X }
- X
- X printf("\n Articles: %ld\n", articles);
- X printf( " Disk usage: %ld k\n\n", disk_use);
- X
- X if (nblocked) printf("Blocked groups: %3d\n", nblocked);
- X if (nignored) printf("Ignored groups: %3d\n", nignored);
- X}
- X
- Xstatic dump_g_flag(gh)
- Xregister group_header *gh;
- X{
- X printf("Flags: ");
- X if (gh->master_flag & M_BLOCKED) printf(" BLOCKED");
- X if (gh->master_flag & M_EXPIRE) printf(" EXPIRE");
- X if (gh->master_flag & M_MODERATED) printf(" MODERATED");
- X if (gh->master_flag & M_CONTROL) printf(" CONTROL");
- X if (gh->master_flag & M_NO_DIRECTORY) printf(" NO_DIRECTORY");
- X if (gh->master_flag & M_ALWAYS_DIGEST) printf(" ALWAYS_DIGEST");
- X if (gh->master_flag & M_NEVER_DIGEST) printf(" NEVER_DIGEST");
- X if (gh->master_flag & M_INCLUDE_OLD) printf(" INCL_OLD");
- X if (gh->master_flag & M_AUTO_RECOLLECT) printf(" RECOLLECT");
- X if (gh->master_flag & M_AUTO_ARCHIVE) printf(" ARCHIVE");
- X if (gh->master_flag & M_IGNORE_GROUP) printf(" IGNORE");
- X if (gh->master_flag & M_VALID) printf(" VALID");
- X printf("\n");
- X}
- X
- Xstatic dump_m_entry(gh)
- Xregister group_header *gh;
- X{
- X update_group(gh);
- X
- X printf("\n%s\t%d\n", gh->group_name, gh->group_num);
- X printf("first/last art: %06ld %06d\n",
- X gh->first_db_article, gh->last_db_article);
- X printf(" active info: %06ld %06d\n",
- X gh->first_a_article, gh->last_a_article);
- X printf("Offsets: index->%ld, data->%ld\n",
- X gh->index_write_offset,
- X gh->data_write_offset);
- X if (gh->master_flag & M_AUTO_ARCHIVE)
- X printf("Archive file: %s\n", gh->archive_file);
- X if (gh->master_flag)
- X dump_g_flag(gh);
- X}
- X
- X#define valerr( xxx , tp) { \
- X if (verbose) { printf xxx ; fl; } \
- X err_type = tp; \
- X goto err; \
- X}
- X
- Xstatic validate_group(gh)
- Xgroup_header *gh;
- X{
- X FILE *data, *ix;
- X off_t data_offset, next_offset;
- X cross_post_number cross_post;
- X article_number cur_article;
- X int n, err_type;
- X
- X data = ix = NULL;
- X
- X if (gh->first_db_article == (gh->last_db_article + 1)
- X && gh->index_write_offset == 0)
- X return 1;
- X
- X if (verbose) { printf("\r%s: ", gh->group_name); clrline(); }
- X
- X if (init_group(gh) <= 0) {
- X printf("NO DIRECTORY (ok)");
- X return 1; /* no directory/ignored */
- X }
- X
- X update_group(gh);
- X
- X if (gh->master_flag & M_BLOCKED) {
- X if (verbose) printf("BLOCKED (ok)\n");
- X return 1;
- X }
- X
- X /*
- X * Check for major inconcistencies.
- X * Sometimes, news expire will reset article numbers
- X * to start from 0 again
- X */
- X
- X if (gh->last_db_article == 0) {
- X return 1;
- X }
- X
- X#ifdef RENUMBER_DANGER
- X if (gh->first_a_article > (gh->last_db_article + 1) ||
- X gh->last_db_article > gh->last_a_article ||
- X gh->first_db_article > gh->first_a_article) {
- X
- X if (verbose)
- X printf("RENUMBERING OF ARTICLES (active=%ld..%ld master=%ld..%ld)",
- X gh->first_a_article, gh->last_a_article,
- X gh->first_db_article, gh->last_db_article);
- X err_type = 99;
- X goto err;
- X }
- X#endif
- X
- X ix = open_data_file(gh, 'x', OPEN_READ);
- X if (ix == NULL) valerr(("NO INDEX FILE"), 1);
- X
- X data = open_data_file(gh, 'd', OPEN_READ);
- X if (data == NULL) valerr(("NO DATA FILE"), 2);
- X
- X cur_article = gh->first_db_article - 1;
- X
- X while (cur_article <= gh->last_db_article) {
- X if (s_hangup || s_keyboard) goto out;
- X
- X data_offset = ftell(data);
- X
- X switch (db_read_art(data)) {
- X case 0:
- X if (data_offset == gh->data_write_offset) goto out;
- X valerr(("No header for article # %ld", (long)cur_article+1), 3);
- X case 1:
- X break;
- X case -1:
- X valerr(("END OF FILE on DATA FILE"), 4);
- X }
- X
- X if (db_hdr.dh_number <= 0 || cur_article > db_hdr.dh_number)
- X valerr(("OUT OF SEQUENCE: %ld after %ld", (long)db_hdr.dh_number, (long)cur_article), 11);
- X
- X if (cur_article < db_hdr.dh_number) {
- X if (db_data.dh_type == DH_SUB_DIGEST)
- X valerr(("NO DIGEST HEADER: %ld", (long)db_hdr.dh_number), 5);
- X
- X do {
- X cur_article++;
- X if (!db_read_offset(ix, &next_offset))
- X valerr(("NO INDEX FOR ARTICLE %ld", (long)cur_article), 6);
- X
- X if (data_offset != next_offset)
- X valerr(("OFFSET ERROR: %ld: %ld != %ld", (long)cur_article, (long)data_offset, (long)next_offset), 7);
- X } while (cur_article < db_hdr.dh_number);
- X }
- X
- X for (n = 0; n < db_hdr.dh_cross_postings; n++) {
- X cross_post = NETW_CROSS_INT(db_data.dh_cross[n]);
- X if (cross_post < master.number_of_groups) continue;
- X valerr(("CROSS POST RANGE ERROR: %ld (article # %ld)", (long)cross_post, (long)cur_article), 8);
- X }
- X }
- X
- X out:
- X if (!s_keyboard && !s_hangup) {
- X data_offset = ftell(data);
- X if (data_offset != gh->data_write_offset)
- X valerr(("DATA OFFSET %ld != %ld", (long)gh->data_write_offset, (long)data_offset), 9);
- X data_offset = ftell(ix);
- X if (data_offset != gh->index_write_offset)
- X valerr(("INDEX OFFSET %ld != %ld", (long)gh->index_write_offset, (long)data_offset), 10);
- X }
- X
- X fclose(data);
- X fclose(ix);
- X if (verbose) printf("OK");
- X return 1;
- X
- X err:
- X if (data != NULL) fclose(data);
- X if (ix != NULL) fclose(ix);
- X log_entry('V', "%s: database error %d", gh->group_name, err_type);
- X if (verbose) {
- X putchar(NL);
- X dump_m_entry(gh);
- X }
- X
- X if (!pre_input) {
- X ding();
- X
- X for (;;) {
- X switch (get_cmd((char *)NULL,
- X"\nRepair group Y)es N)o E)nter Q)uit")) {
- X case 'Y':
- X break;
- X case 'N':
- X return 0;
- X case 'Q':
- X s_keyboard++;
- X return 0;
- X case 'E':
- X group_admin(gh);
- X continue;
- X default:
- X continue;
- X }
- X break;
- X }
- X }
- X
- X send_master(SM_RECOLLECT, gh, SP, 0L);
- X return 0;
- X}
- X
- Xstatic dump_group(gh)
- Xgroup_header *gh;
- X{
- X FILE *data, *ix;
- X off_t offset;
- X cross_post_number cross_post;
- X article_number first_article;
- X int n;
- X
- X if (init_group(gh) <= 0)
- X printf("cannot access group %s\n", gh->group_name);
- X
- X update_group(gh);
- X
- X first_article = get_entry("First article",
- X (long)gh->first_db_article,
- X (long)gh->last_db_article);
- X
- X if (first_article < 0) first_article = gh->first_db_article;
- X if (first_article <= 0) first_article = 1;
- X
- X ix = open_data_file(gh, 'x', OPEN_READ);
- X data = open_data_file(gh, 'd', OPEN_READ);
- X if (ix == NULL || data == NULL) goto err;
- X
- X fseek(ix, get_index_offset(gh, first_article), 0);
- X if (!db_read_offset(ix, &offset)) goto err;
- X fseek(data, offset, 0);
- X
- X clrdisp();
- X pg_init(1, 1);
- X
- X for (;;) {
- X if (s_hangup || s_keyboard) break;
- X
- X if (pg_scroll(6)) {
- X s_keyboard = 1;
- X break;
- X }
- X
- X offset = ftell(data);
- X
- X switch (db_read_art(data)) {
- X case 0:
- X goto out;
- X case 1:
- X break;
- X case -1:
- X goto err;
- X }
- X
- X printf("\noffset = %ld, article # = %ld",
- X (long)offset, (long)(db_hdr.dh_number));
- X
- X switch (db_data.dh_type) {
- X case DH_DIGEST_HEADER:
- X printf(" (digest header)\n");
- X break;
- X case DH_SUB_DIGEST:
- X printf(" (digest sub-article)\n");
- X break;
- X case DH_NORMAL:
- X putchar(NL);
- X break;
- X }
- X
- X if (db_hdr.dh_cross_postings) {
- X printf("xpost(%d):", db_hdr.dh_cross_postings);
- X
- X for (n = 0; n < db_hdr.dh_cross_postings; n++) {
- X cross_post = NETW_CROSS_INT(db_data.dh_cross[n]);
- X printf(" %d", cross_post);
- X }
- X putchar(NL);
- X }
- X
- X printf("ts=%lu hp=%ld, fp=+%d, lp=%ld, ref=%d%s, lines=%d\n",
- X (long unsigned)db_hdr.dh_date, (long)db_hdr.dh_hpos,
- X (int)db_hdr.dh_fpos, (long)db_hdr.dh_lpos,
- X db_hdr.dh_replies & 0x7f,
- X (db_hdr.dh_replies & 0x80) ? "+Re" : "",
- X db_hdr.dh_lines);
- X
- X if (db_hdr.dh_sender_length)
- X printf("Sender(%d): %s\n", db_hdr.dh_sender_length, db_data.dh_sender);
- X else
- X printf("No sender\n");
- X
- X if (db_hdr.dh_subject_length)
- X printf("Subj(%d): %s\n", db_hdr.dh_subject_length, db_data.dh_subject);
- X else
- X printf("No subject\n");
- X }
- X
- X out:
- X if (!s_keyboard && !s_hangup && ftell(data) != gh->data_write_offset)
- X goto err;
- X
- X fclose(data);
- X fclose(ix);
- X return 1;
- X
- X err:
- X if (data != NULL) fclose(data);
- X if (ix != NULL) fclose(ix);
- X printf("\n*** DATABASE INCONSISTENCY DETECTED - run V)alidate\n");
- X return 0;
- X}
- X
- Xstatic kill_master(term)
- Xint term;
- X{
- X switch (proto_lock(I_AM_MASTER, term ? PL_TERMINATE : PL_WAKEUP_SOFT)) {
- X case 1:
- X if (verbose)
- X printf("sent %s signal to master\n", term ? "termination" : "wakeup");
- X break;
- X case 0:
- X printf("cannot signal master\n");
- X break;
- X case -1:
- X if (verbose) printf("master is not running\n");
- X break;
- X }
- X}
- X
- Xstatic master_admin()
- X{
- X register char c;
- X int cur_group;
- X long value;
- X register group_header *gh;
- X
- X exec_chdir_to = db_directory;
- X
- X for (;;) {
- X switch (c = get_cmd(
- X"\nD)ump F)iles G)roup K)ill O)ptions S)tat T)race",
- X"MASTER")) {
- X
- X case 'G':
- X cur_group = (int)get_entry("Group number",
- X 0L, (long)(master.number_of_groups - 1));
- X if (cur_group >= 0)
- X dump_m_entry(&active_groups[cur_group]);
- X break;
- X
- X case 'D':
- X do {
- X c = get_cmd(
- X"\nA)ll B)locked E)mpty H)oles I)gnored N)on-empty V)alid in(W)alid",
- X"DUMP");
- X cur_group = -1;
- X pg_init(1, 1);
- X
- X while (++cur_group < master.number_of_groups) {
- X if (s_keyboard || s_hangup) break;
- X
- X gh = &active_groups[cur_group];
- X#define NODUMP(cond) if (cond) continue; break
- X switch (c) {
- X case 'N':
- X NODUMP(gh->index_write_offset == 0);
- X case 'E':
- X NODUMP(gh->index_write_offset != 0);
- X case 'H':
- X NODUMP(gh->first_a_article >= gh->first_db_article);
- X case 'B':
- X NODUMP((gh->master_flag & M_BLOCKED) == 0);
- X case 'I':
- X NODUMP((gh->master_flag & M_IGNORE_GROUP) == 0);
- X case 'V':
- X NODUMP((gh->master_flag & M_VALID) == 0);
- X case 'W':
- X NODUMP(gh->master_flag & M_VALID);
- X default:
- X s_keyboard = 1; continue;
- X }
- X
- X if (pg_scroll(6)) break;
- X dump_m_entry(gh);
- X }
- X } while (!s_keyboard && !s_hangup);
- X break;
- X
- X case 'F':
- X find_files((group_header *)NULL);
- X break;
- X
- X case 'O':
- X c = get_cmd("r)epeat_delay e)xpire_level", "OPTION");
- X if (c != 'R' && c != 'E') break;
- X value = get_entry("Option value", 1L, 10000L);
- X if (value < 0) break;
- X send_master(SM_SET_OPTION, (group_header *)NULL, tolower(c), value);
- X break;
- X
- X case 'S':
- X master_status();
- X break;
- X
- X case 'T':
- X send_master(SM_SET_OPTION, (group_header *)NULL, 't', -1L);
- X break;
- X
- X case 'K':
- X if (admin_confirm("Stop nn Master", 0))
- X kill_master(1);
- X break;
- X
- X default:
- X exec_chdir_to = NULL;
- X return;
- X }
- X }
- X}
- X
- X
- Xstatic log_admin()
- X{
- X char command[FILENAME + 100], c;
- X
- X if (pre_input && *pre_input == NUL) {
- X c = SP;
- X goto log_tail;
- X }
- X
- X loop:
- X
- X c = get_cmd(
- X"\n1-9)tail A)dm C)ollect E)rr N)ntp G)roup R)eport e(X)pire .)all @)clean",
- X"LOG");
- X
- X if (c < SP || c == 'Q') return;
- X
- X if (c == '@') {
- X if (admin_confirm("Truncation", 0)) {
- X sprintf(command, "%s.old", log_file);
- X unlink(command);
- X if (link(log_file, command) < 0) goto tr_failed;
- X if (unlink(log_file) < 0) {
- X unlink(command);
- X goto tr_failed;
- X }
- X log_entry('A', "Log Truncated");
- X chmod(log_file, 0666);
- X }
- X return;
- X
- X tr_failed:
- X printf("Truncation failed -- check permissions etc.\n");
- X goto loop;
- X }
- X
- X if (c == 'G') {
- X char *groupname;
- X
- X if ((groupname = get_groupname()) == NULL) goto loop;
- X sprintf(command, "fgrep '%s' %s | %s",
- X groupname, log_file, pager);
- X system(command);
- X
- X goto loop;
- X }
- X
- X log_tail:
- X if (c == '$' || c == SP || isdigit(c)) {
- X int n;
- X
- X n = isdigit(c) ? 10 * (c - '0') : 10;
- X sprintf(command, "tail -%d %s", n, log_file);
- X system(command);
- X goto loop;
- X }
- X
- X if (c == '*') {
- X c = '.';
- X }
- X
- X sprintf(command, "grep '^%c:' %s | %s", c, log_file, pager);
- X system(command);
- X
- X goto loop;
- X}
- X
- X
- Xstatic flag_admin(gh, mode_str, set_flag)
- Xgroup_header *gh;
- Xchar *mode_str;
- Xint set_flag;
- X{
- X char buffer[50];
- X int new_flag = 0;
- X
- X putchar(NL);
- X
- X dump_g_flag(gh);
- X
- X sprintf(buffer, "%s FLAG", mode_str);
- X
- X switch (get_cmd(
- X"\nA)lways_digest N)ever_digest M)oderated C)ontrol no_(D)ir",
- Xbuffer)) {
- X
- X default:
- X return;
- X
- X case 'M':
- X new_flag = M_MODERATED;
- X break;
- X
- X case 'C':
- X new_flag = M_CONTROL;
- X break;
- X
- X case 'D':
- X new_flag = M_NO_DIRECTORY;
- X break;
- X
- X case 'A':
- X new_flag = M_ALWAYS_DIGEST;
- X break;
- X
- X case 'N':
- X new_flag = M_NEVER_DIGEST;
- X break;
- X }
- X
- X if (new_flag & (M_CONTROL | M_NO_DIRECTORY))
- X if (!admin_confirm("Flag Change", 0))
- X new_flag = 0;
- X
- X if (new_flag) {
- X if (set_flag) {
- X if (gh->master_flag & new_flag)
- X new_flag = 0;
- X else {
- X send_master(SM_SET_FLAG, gh, 's', (long)new_flag);
- X gh->master_flag |= new_flag;
- X }
- X } else {
- X if ((gh->master_flag & new_flag) == 0)
- X new_flag = 0;
- X else {
- X send_master(SM_SET_FLAG, gh, 'c', (long)new_flag);
- X gh->master_flag &= ~new_flag;
- X }
- X }
- X }
- X
- X if (new_flag == 0)
- X printf("NO CHANGE\n");
- X else
- X dump_g_flag(gh);
- X}
- X
- X
- Xstatic rmgroup(gh)
- Xgroup_header *gh;
- X{
- X char command[FILENAME*2];
- X
- X if (!file_exist(news_active, "w")) {
- X printf("Not privileged to run rmgroup\n");
- X return;
- X }
- X
- X sprintf(command, "%s/rmgroup %s", news_lib_directory, gh->group_name);
- X system(command);
- X any_key(0);
- X gh->master_flag &= ~M_VALID; /* just for nnadmin */
- X gh->master_flag |= M_IGNORE_A;
- X}
- X
- Xstatic group_admin(gh)
- Xregister group_header *gh;
- X{
- X char *groupname, gbuf[FILENAME], dirbuf[FILENAME];
- X
- X if (gh != NULL) goto have_group;
- X
- X new_group:
- X if ((groupname = get_groupname()) == NULL) return;
- X
- X gh = lookup(groupname);
- X if (gh == NULL) {
- X printf("No group named %s\n", groupname);
- X goto new_group;
- X }
- X
- X have_group:
- X if (!use_nntp && init_group(gh)) {
- X strcpy(dirbuf, group_path_name);
- X dirbuf[strlen(dirbuf)-1] = NUL;
- X exec_chdir_to = dirbuf;
- X }
- X
- X sprintf(gbuf, "GROUP %s", gh->group_name);
- X
- X for (;;) {
- X switch (get_cmd(
- X"\nD)ata E)xpire F)iles G)roup H)eader R)ecollect V)alidate Z)ap",
- Xgbuf)) {
- X case 'D':
- X dump_group(gh);
- X break;
- X
- X case 'V':
- X verbose = 1;
- X validate_group(gh);
- X putchar(NL);
- X break;
- X
- X case 'H':
- X dump_m_entry(gh);
- X break;
- X
- X case 'F':
- X find_files(gh);
- X break;
- X
- X case 'S':
- X flag_admin(gh, "Set", 1);
- X break;
- X
- X case 'C':
- X flag_admin(gh, "Clear", 0);
- X break;
- X
- X case 'R':
- X if (admin_confirm("Recolletion of Group", 0))
- X send_master(SM_RECOLLECT, gh, SP, 0L);
- X break;
- X
- X case 'Z':
- X if (admin_confirm("Remove Group (run rmgroup)", 1))
- X rmgroup(gh);
- X break;
- X
- X case 'E':
- X if (admin_confirm("Expire Group", 0))
- X send_master(SM_EXPIRE, gh, SP, 0L);
- X break;
- X
- X case 'G':
- X goto new_group;
- X
- X default:
- X exec_chdir_to = NULL;
- X return;
- X }
- X }
- X}
- X
- X
- Xstatic show_config()
- X{
- X#ifdef NNTP
- X extern char nntp_server[];
- X#endif
- X
- X printf("\nConfiguration:\n\n");
- X printf("BIN: %s\nLIB: %s\nNEWS SPOOL: %s\nNEWS LIB: %s\n",
- X bin_directory,
- X lib_directory,
- X news_directory,
- X news_lib_directory);
- X
- X printf("DB: %s %s\n", db_directory,
- X db_data_directory != NULL ? db_data_directory :
- X "(per-group files in group directories)");
- X
- X printf("ACTIVE: %s\n", news_active);
- X
- X#ifdef NNTP
- X if (use_nntp)
- X printf("NNTP ACTIVE. server=%s\n", nntp_server);
- X else
- X printf("NNTP NOT ACTIVE\n");
- X#endif
- X
- X#ifdef NETWORK_DATABASE
- X printf("Database is machine independent (network format).\n");
- X#ifdef NETWORK_BYTE_ORDER
- X printf("Local system assumes to use network byte order\n");
- X#endif
- X#else
- X printf("Database format is machine dependent (byte order and alignment)\n");
- X#endif
- X printf("Database version: %d\n", NNDB_MAGIC & 0xff);
- X
- X#ifdef STATISTICS
- X printf("Recording usage statistics\n");
- X#else
- X printf("No usage statistics are recorded\n");
- X#endif
- X
- X printf("Mail delivery program: %s\n", REC_MAIL);
- X#ifdef APPEND_SIGNATURE
- X printf("Query for appending .signature ENABLED\n");
- X#else
- X printf("Query for appending .signature DISABLED\n");
- X#endif
- X
- X printf("Max pathname length is %d bytes\n", FILENAME-1);
- X}
- X
- X
- Xadmin_mode(input_string)
- Xchar *input_string;
- X{
- X register group_header *gh;
- X int was_raw = unset_raw();
- X
- X if (input_string && *input_string) {
- X pre_input = input_string;
- X } else {
- X pre_input = NULL;
- X printf("\nMaster is%s running\n",
- X proto_lock(I_AM_MASTER, PL_CHECK) < 0 ? " NOT" : "");
- X }
- X
- X for (;;) {
- X switch(get_cmd(
- X"\nC)onf E)xpire G)roups I)nit L)og M)aster Q)uit S)tat U)pdate V)alidate W)akeup",
- X"ADMIN")) {
- X
- X case 'M':
- X master_admin();
- X break;
- X
- X case 'W':
- X kill_master(0);
- X break;
- X
- X case 'E':
- X if (admin_confirm("Expire All Groups", 1))
- X send_master(SM_EXPIRE, (group_header *)NULL, SP, 0L);
- X break;
- X
- X case 'I':
- X if (admin_confirm("INITIALIZATION, i.e. recollect all groups", 1))
- X send_master(SM_RECOLLECT, (group_header *)NULL, SP, 0L);
- X break;
- X
- X case 'G':
- X group_admin((group_header *)NULL);
- X break;
- X
- X case 'L':
- X log_admin();
- X break;
- X
- X case 'S':
- X master_status();
- X break;
- X
- X case 'C':
- X show_config();
- X break;
- X
- X case 'U':
- X update_master();
- X break;
- X
- X case 'Z':
- X verbose = 0;
- X /* FALL THRU */
- X
- X case 'V':
- X Loop_Groups_Sorted(gh) {
- X if (s_hangup || s_keyboard) break;
- X validate_group(gh);
- X }
- X verbose = 1;
- X break;
- X
- X case '=':
- X verbose = !verbose;
- X break;
- X
- X case 'Q':
- X if (was_raw) raw();
- X return;
- X }
- X }
- X}
- END_OF_FILE
- if test 21406 -ne `wc -c <'admin.c'`; then
- echo shar: \"'admin.c'\" unpacked with wrong size!
- fi
- # end of 'admin.c'
- fi
- if test -f 'help/help.read' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'help/help.read'\"
- else
- echo shar: Extracting \"'help/help.read'\" \(13 characters\)
- sed "s/^X//" >'help/help.read' <<'END_OF_FILE'
- X;:Chelp.more
- END_OF_FILE
- if test 13 -ne `wc -c <'help/help.read'`; then
- echo shar: \"'help/help.read'\" unpacked with wrong size!
- fi
- # end of 'help/help.read'
- fi
- if test -f 'inews/inews.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'inews/inews.c'\"
- else
- echo shar: Extracting \"'inews/inews.c'\" \(8001 characters\)
- sed "s/^X//" >'inews/inews.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *sccsid = "@(#)inews.c 1.16 (Berkeley) 8/27/89";
- X#endif
- X
- X/*
- X * Itty-bitty inews for talking to remote server.
- X * Simply accept input on stdin (or via a named file) and dump this
- X * to the server; add a From: and Path: line if missing in the original.
- X * Print meaningful errors from the server.
- X * Limit .signature files to MAX_SIGNATURE lines.
- X * No processing of command line options.
- X *
- X * Original by Steven Grady <grady@ucbvax.Berkeley.EDU>, with thanks from
- X * Phil Lapsley <phil@ucbvax.berkeley.edu>
- X * Send bug reports to Stan Barber <sob@bcm.tmc.edu>
- X */
- X
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <ctype.h>
- X#include "conf.h"
- X#include "nntp.h"
- X#ifndef FOR_NN
- X#ifdef USG
- X#include <string.h>
- X#else not USG
- X#include <strings.h>
- X#endif not USG
- X#endif
- X
- X#define MAX_SIGNATURE 4
- X
- Xextern FILE *ser_wr_fp;
- X
- Xchar host_name[256];
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X char line[NNTP_STRLEN], s[NNTP_STRLEN];
- X int seen_fromline, in_header, seen_header;
- X int response;
- X char *server;
- X char *getserverbyfile();
- X register char *cp;
- X
- X ++argv;
- X while (argc > 1)
- X if (*argv[0] == '-') {
- X ++argv;
- X --argc;
- X } else
- X break;
- X
- X if (argc > 1) {
- X if (freopen(*argv, "r", stdin) == NULL) {
- X perror(*argv);
- X exit(1);
- X }
- X }
- X
- X uname(host_name);
- X
- X server = getserverbyfile(SERVER_FILE);
- X if (server == NULL) {
- X fprintf(stderr,
- X "Can't get the name of the news server from %s.\n",
- X SERVER_FILE);
- X fprintf(stderr,
- X "Either fix this file, or put NNTPSERVER in your enviroment.\n");
- X exit(1);
- X }
- X
- X response = server_init(server);
- X if (response < 0) {
- X printf("Couldn't connect to %s news server, try again later.\n",
- X server);
- X exit(1);
- X }
- X
- X if (handle_server_response(response, server) < 0
- X || response == OK_NOPOST) {
- X close_server();
- X exit(1);
- X }
- X
- X put_server("POST");
- X (void) get_server(line, sizeof(line));
- X if (*line != CHAR_CONT) {
- X if (atoi(line) == ERR_NOPOST) {
- X close_server();
- X fprintf(stderr,
- X "Sorry, you can't post from this machine.\n");
- X exit(1);
- X } else {
- X close_server();
- X fprintf(stderr, "Remote error: %s\n", line);
- X exit(1);
- X }
- X }
- X
- X in_header = 1;
- X seen_header = 0;
- X seen_fromline = 0;
- X
- X while (gets(s) != NULL) {
- X if (s[0] == '.') /* Single . is eof, so put in extra one */
- X (void) fputc('.', ser_wr_fp);
- X if (in_header && strneql(s, "From:", sizeof("From:")-1)) {
- X seen_header = 1;
- X seen_fromline = 1;
- X }
- X if (in_header && s[0] == '\0') {
- X if (seen_header) {
- X in_header = 0;
- X if (!seen_fromline)
- X gen_frompath();
- X } else {
- X continue;
- X }
- X } else if (in_header) {
- X if (valid_header(s))
- X seen_header = 1;
- X else
- X continue;
- X }
- X fprintf(ser_wr_fp, "%s\r\n", s);
- X }
- X
- X append_signature();
- X
- X fprintf(ser_wr_fp, ".\r\n");
- X (void) fflush(ser_wr_fp);
- X (void) get_server(line, sizeof(line));
- X if (*line != CHAR_OK) {
- X if (atoi(line) == ERR_POSTFAIL) {
- X close_server();
- X printf("Article not accepted by server; not posted.\n");
- X for (cp = line + 4; *cp && *cp != '\r'; cp++)
- X if (*cp == '\\')
- X putchar('\n');
- X else
- X putchar(*cp);
- X exit(1);
- X } else {
- X close_server();
- X fprintf(stderr, "Remote error: %s\n", line);
- X exit(1);
- X }
- X }
- X
- X /*
- X * Close server sends the server a
- X * "quit" command for us, which is why we don't send it.
- X */
- X
- X close_server();
- X
- X exit(0);
- X}
- X
- X/*
- X * append_signature -- append the person's .signature file if
- X * they have one. Limit .signature to MAX_SIGNATURE lines.
- X * The rn-style DOTDIR environmental variable is used if present.
- X */
- X
- Xappend_signature()
- X{
- X char line[256], sigfile[256];
- X char *cp;
- X struct passwd *passwd;
- X FILE *fp;
- X char *index(), *getenv();
- X int count = 0;
- X char *dotdir;
- X
- X passwd = getpwuid(getuid());
- X if (passwd == NULL)
- X return;
- X#ifdef DO_DOTDIR
- X if ((dotdir = getenv("DOTDIR")) == NULL)
- X#endif
- X {
- X dotdir = passwd->pw_dir;
- X }
- X
- X if (dotdir[0] == '~') {
- X (void) strcpy(sigfile, passwd->pw_dir);
- X (void) strcat(sigfile, &dotdir[1]);
- X } else {
- X (void) strcpy(sigfile, dotdir);
- X }
- X (void) strcat(sigfile, "/");
- X (void) strcat(sigfile, ".signature");
- X
- X#ifdef DEBUG
- X fprintf(stderr,"sigfile = '%s'\n", sigfile);
- X#endif
- X
- X fp = fopen(sigfile, "r");
- X if (fp == NULL)
- X return;
- X
- X#ifdef DEBUG
- X fprintf(stderr,"sigfile opened OK\n");
- X#endif
- X
- X fprintf(ser_wr_fp, "--\r\n");
- X while (fgets(line, sizeof (line), fp)) {
- X count++;
- X if (count > MAX_SIGNATURE) {
- X fprintf(stderr,
- X "Warning: .signature files should be no longer than %d lines.\n",
- X MAX_SIGNATURE);
- X fprintf(stderr,
- X "(Only %d lines of your .signature were posted.)\n",
- X MAX_SIGNATURE);
- X break;
- X }
- X if (cp = index(line, '\n'))
- X *cp = '\0';
- X fprintf(ser_wr_fp, "%s\r\n", line);
- X }
- X (void) fclose(fp);
- X#ifdef DEBUG
- X printf(".signature appended (from %s)\n", sigfile);
- X#endif
- X}
- X
- X
- X/*
- X * gen_frompath -- generate From: and Path: lines, in the form
- X *
- X * From: user@host.domain (full_name)
- X * Path: host!user
- X *
- X * This routine should only be called if the message doesn't have
- X * a From: line in it.
- X */
- X
- Xgen_frompath()
- X{
- X char *full_name;
- X char *cp;
- X struct passwd *passwd;
- X char *index(), *getenv();
- X
- X passwd = getpwuid(getuid());
- X
- X full_name = getenv("NAME");
- X if (full_name == NULL) {
- X full_name = passwd->pw_gecos;
- X if ((cp = index(full_name, ',')))
- X *cp = '\0';
- X }
- X
- X#ifdef DOMAIN
- X#ifdef HIDDENNET
- X fprintf(ser_wr_fp, "From: %s@%s (",
- X passwd->pw_name,
- X DOMAIN);
- X#else /* HIDDENNET */
- X
- X /* A heuristic to see if we should tack on a domain */
- X
- X cp = index(host_name, '.');
- X if (cp)
- X fprintf(ser_wr_fp, "From: %s@%s (",
- X passwd->pw_name,
- X host_name);
- X else
- X fprintf(ser_wr_fp, "From: %s@%s.%s (",
- X passwd->pw_name,
- X host_name,
- X DOMAIN);
- X#endif /* HIDDENNET */
- X#else
- X fprintf(ser_wr_fp, "From: %s@%s (",
- X passwd->pw_name,
- X host_name);
- X#endif
- X
- X for (cp = full_name; *cp != '\0'; ++cp)
- X if (*cp != '&')
- X putc(*cp, ser_wr_fp);
- X else { /* Stupid & hack. God damn it. */
- X putc(toupper(passwd->pw_name[0]), ser_wr_fp);
- X fprintf(ser_wr_fp, passwd->pw_name+1);
- X }
- X
- X fprintf(ser_wr_fp, ")\r\n");
- X
- X#ifdef HIDDENNET
- X /* Only the login name - nntp server will add uucp name */
- X fprintf(ser_wr_fp, "Path: %s\r\n", passwd->pw_name);
- X#else /* HIDDENNET */
- X fprintf(ser_wr_fp, "Path: %s!%s\r\n", host_name, passwd->pw_name);
- X#endif /* HIDDENNET */
- X}
- X
- X
- X/*
- X * strneql -- determine if two strings are equal in the first n
- X * characters, ignoring case.
- X *
- X * Parameters: "a" and "b" are the pointers
- X * to characters to be compared.
- X * "n" is the number of characters to compare.
- X *
- X * Returns: 1 if the strings are equal, 0 otherwise.
- X *
- X * Side effects: None.
- X */
- X
- Xstrneql(a, b, n)
- Xregister char *a, *b;
- Xint n;
- X{
- X char lower();
- X
- X while (n && lower(*a) == lower(*b)) {
- X if (*a == '\0')
- X return (1);
- X a++;
- X b++;
- X n--;
- X }
- X if (n)
- X return (0);
- X else
- X return (1);
- X}
- X
- X/*
- X * lower -- convert a character to lower case, if it's
- X * upper case.
- X *
- X * Parameters: "c" is the character to be
- X * converted.
- X *
- X * Returns: "c" if the character is not
- X * upper case, otherwise the lower
- X * case eqivalent of "c".
- X *
- X * Side effects: None.
- X */
- X
- Xchar lower(c)
- Xregister char c;
- X{
- X if (isascii(c) && isupper(c))
- X c = c - 'A' + 'a';
- X return(c);
- X}
- X
- X
- X/*
- X * valid_header -- determine if a line is a valid header line
- X *
- X * Parameters: "h" is the header line to be checked.
- X *
- X * Returns: 1 if valid, 0 otherwise
- X *
- X * Side Effects: none
- X *
- X */
- X
- Xint valid_header(h)
- Xregister char *h;
- X{
- X char *index();
- X char *colon, *space;
- X
- X /*
- X * blank or tab in first position implies this is a continuation header
- X */
- X if (h[0] == ' ' || h[0] == '\t')
- X return (1);
- X
- X /*
- X * just check for initial letter, colon, and space to make
- X * sure we discard only invalid headers
- X */
- X colon = index(h, ':');
- X space = index(h, ' ');
- X if (isalpha(h[0]) && colon && space == colon + 1)
- X return (1);
- X
- X /*
- X * anything else is a bad header -- it should be ignored
- X */
- X return (0);
- X}
- END_OF_FILE
- if test 8001 -ne `wc -c <'inews/inews.c'`; then
- echo shar: \"'inews/inews.c'\" unpacked with wrong size!
- fi
- # end of 'inews/inews.c'
- fi
- if test -f 'variable.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'variable.c'\"
- else
- echo shar: Extracting \"'variable.c'\" \(20923 characters\)
- sed "s/^X//" >'variable.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- X *
- X * Variabel setting and display
- X */
- X
- X#include "config.h"
- X#include "keymap.h"
- X
- Ximport in_init;
- X
- Ximport char /* string variables */
- X *bak_suffix,
- X *bug_address,
- X *decode_header_file,
- X *default_distribution,
- X *default_save_file,
- X *editor_program,
- X *extra_mail_headers,
- X *extra_news_headers,
- X *header_lines,
- X *folder_directory,
- X included_mark[],
- X *mail_box,
- X *mail_record,
- X *mail_script,
- X *mailer_program,
- X attributes[],
- X *newsrc_file,
- X *news_record,
- X *news_script,
- X *pager,
- X patch_command[],
- X printer[],
- X *response_dflt_answer,
- X *save_counter_format,
- X *spell_checker,
- X unshar_command[],
- X *unshar_header_file,
- X *user_shell;
- X
- Ximport int /* boolean variables */
- X also_cross_postings,
- X also_subgroups,
- X append_sig_mail,
- X append_sig_post,
- X auto_junk_seen,
- X auto_preview_mode,
- X case_fold_search,
- X compress_mode,
- X conf_append,
- X conf_auto_quit,
- X conf_create,
- X conf_dont_sleep,
- X conf_group_entry,
- X conf_junk_seen,
- X delay_redraw,
- X do_kill_handling,
- X dont_sort_articles,
- X dont_sort_folders,
- X dont_split_digests,
- X edit_patch_command,
- X edit_print_command,
- X edit_unshar_command,
- X empty_answer_check,
- X flow_control,
- X flush_typeahead,
- X fmt_rptsubj,
- X include_art_id,
- X include_full_header,
- X keep_rc_backup,
- X keep_unsubscribed,
- X keep_unsub_long,
- X long_menu,
- X macro_debug,
- X mailer_pipe_input,
- X mark_overlap,
- X match_parts_equal,
- X monitor_mode,
- X novice,
- X preview_mark_read,
- X query_signature,
- X quick_save,
- X quick_unread_count,
- X repeat_group_query,
- X report_cost_on_exit,
- X retain_seen_status,
- X save_report,
- X scroll_clear_page,
- X select_leave_next,
- X select_on_sender,
- X seq_cross_filtering,
- X shell_restrictions,
- X show_article_date,
- X show_current_time,
- X silent,
- X slow_mode,
- X suggest_save_file,
- X tidy_newsrc,
- X use_mail_folders,
- X use_mmdf_folders,
- X use_selections,
- X use_visible_bell;
- X
- Ximport int /* integer variables */
- X also_read_articles,
- X article_limit,
- X conf_entry_limit,
- X collapse_subject,
- X Columns,
- X data_bits,
- X Debug,
- X decode_skip_prefix,
- X entry_message_limit,
- X expired_msg_delay,
- X first_page_lines,
- X fmt_linenum,
- X Lines,
- X match_skip_prefix,
- X min_pv_window,
- X new_group_action,
- X newsrc_update_freq,
- X orig_to_include_mask,
- X overlap,
- X preview_continuation,
- X preview_window,
- X re_layout,
- X response_check_pause,
- X retry_on_error,
- X save_counter_offset,
- X slow_speed,
- X sort_mode,
- X subject_match_limit,
- X wrap_headers;
- X
- X#ifdef NNTP
- Ximport char *nntp_cache_dir;
- Ximport int nntp_cache_size, nntp_debug;
- X#endif
- X
- Ximport key_type /* key strokes */
- X comp1_key,
- X comp2_key,
- X help_key,
- X erase_key,
- X delword_key,
- X kill_key;
- X
- X#undef STR
- X#undef BOOL
- X#undef INT
- X#undef KEY
- X#undef SPEC
- X#undef SAFE
- X#undef INIT
- X
- X
- X#define V_STRING 0x1000
- X#define V_BOOLEAN 0x2000
- X#define V_INTEGER 0x3000
- X#define V_KEY 0x4000
- X#define V_SPECIAL 0x5000
- X
- X#define V_SAFE 0x0100
- X#define V_INIT 0x0200
- X
- X#define V_MODIFIED 0x8000
- X
- X#define STR V_STRING |
- X#define BOOL V_BOOLEAN |
- X#define INT V_INTEGER |
- X#define KEY V_KEY |
- X#define SPEC V_SPECIAL |
- X
- X#define SAFE V_SAFE |
- X#define INIT V_INIT |
- X
- Xstruct variable_defs {
- X char *var_name;
- X int var_flags;
- X char **var_addr;
- X} variables[] = {
- X "also-subgroups", BOOL INIT 0, (char **)&also_subgroups,
- X "append-signature-mail", BOOL 0, (char **)&append_sig_mail,
- X "append-signature-post", BOOL 0, (char **)&append_sig_post,
- X "attributes", STR 1, (char **)attributes,
- X "auto-junk-seen", BOOL 0, (char **)&auto_junk_seen,
- X "auto-preview-mode", BOOL 0, (char **)&auto_preview_mode,
- X "backup", BOOL 0, (char **)&keep_rc_backup,
- X "backup-suffix", STR 0, (char **)&bak_suffix,
- X "bug-report-address", STR 0, (char **)&bug_address,
- X "case-fold-search", BOOL 0, (char **)&case_fold_search,
- X "collapse-subject", INT 3, (char **)&collapse_subject,
- X "columns", INT 1, (char **)&Columns,
- X "comp1-key", KEY 0, (char **)&comp1_key,
- X "comp2-key", KEY 0, (char **)&comp2_key,
- X "compress", BOOL 0, (char **)&compress_mode,
- X "confirm-append", BOOL 0, (char **)&conf_append,
- X "confirm-auto-quit", BOOL 0, (char **)&conf_auto_quit,
- X "confirm-create", BOOL 0, (char **)&conf_create,
- X "confirm-entry", BOOL 0, (char **)&conf_group_entry,
- X "confirm-entry-limit", INT 0, (char **)&conf_entry_limit,
- X "confirm-junk-seen", BOOL 0, (char **)&conf_junk_seen,
- X "confirm-messages", BOOL 0, (char **)&conf_dont_sleep,
- X "cross-filter-seq", BOOL 0, (char **)&seq_cross_filtering,
- X "cross-post", BOOL 0, (char **)&also_cross_postings,
- X "data-bits", INT 0, (char **)&data_bits,
- X "date", BOOL 0, (char **)&show_article_date,
- X "debug", INT 0, (char **)&Debug,
- X "decode-header-file", STR 0, (char **)&decode_header_file,
- X "decode-skip-prefix", INT 0, (char **)&decode_skip_prefix,
- X "default-distribution", STR 0, (char **)&default_distribution,
- X "default-save-file", STR 3, (char **)&default_save_file,
- X "delay-redraw", BOOL 0, (char **)&delay_redraw,
- X "edit-patch-command", BOOL 0, (char **)&edit_patch_command,
- X "edit-print-command", BOOL 0, (char **)&edit_print_command,
- X "edit-response-check", BOOL 0, (char **)&empty_answer_check,
- X "edit-unshar-command", BOOL 0, (char **)&edit_unshar_command,
- X "editor", STR 0, (char **)&editor_program,
- X "entry-report-limit", INT 0, (char **)&entry_message_limit,
- X "erase-key", KEY 0, (char **)&erase_key,
- X "expert", BOOL 4, (char **)&novice,
- X "expired-message-delay", INT 0, (char **)&expired_msg_delay,
- X "flow-control", BOOL 0, (char **)&flow_control,
- X "flush-typeahead", BOOL 0, (char **)&flush_typeahead,
- X "folder", STR 2, (char **)&folder_directory,
- X "fsort", BOOL 2, (char **)&dont_sort_folders,
- X "header-lines", STR 0, (char **)&header_lines,
- X "help-key", KEY 0, (char **)&help_key,
- X "include-art-id", BOOL 0, (char **)&include_art_id,
- X "include-full-header", BOOL 0, (char **)&include_full_header,
- X "included-mark", STR 1, (char **)included_mark,
- X "keep-unsubscribed", BOOL 0, (char **)&keep_unsubscribed,
- X "kill", BOOL 0, (char **)&do_kill_handling,
- X "kill-key", KEY 0, (char **)&kill_key,
- X "layout", INT 1, (char **)&fmt_linenum,
- X "limit", INT 2, (char **)&article_limit,
- X "lines", INT 1, (char **)&Lines,
- X "long-menu", BOOL 1, (char **)&long_menu,
- X "macro-debug", BOOL 0, (char **)¯o_debug,
- X "mail", STR 2, (char **)&mail_box,
- X "mail-format", BOOL 0, (char **)&use_mail_folders,
- X "mail-header", STR 0, (char **)&extra_mail_headers,
- X "mail-record", STR 2, (char **)&mail_record,
- X "mail-script", STR SAFE 2, (char **)&mail_script,
- X "mailer", STR 0, (char **)&mailer_program,
- X "mailer-pipe-input", BOOL 0, (char **)&mailer_pipe_input,
- X "mark-overlap", BOOL 0, (char **)&mark_overlap,
- X "min-window", INT 1, (char **)&min_pv_window,
- X "mmdf-format", BOOL 0, (char **)&use_mmdf_folders,
- X "monitor", BOOL 0, (char **)&monitor_mode,
- X "new-group-action", INT 0, (char **)&new_group_action,
- X "news-header", STR 0, (char **)&extra_news_headers,
- X "news-record", STR 2, (char **)&news_record,
- X "news-script", STR SAFE 2, (char **)&news_script,
- X "newsrc", STR 2, (char **)&newsrc_file,
- X#ifdef NNTP
- X "nntp-cache-dir", STR INIT 0, (char **)&nntp_cache_dir,
- X "nntp-cache-size", INT INIT 0, (char **)&nntp_cache_size,
- X "nntp-debug", BOOL 0, (char **)&nntp_debug,
- X#endif
- X/* "no....." -- cannot have variable names starting with "no" */
- X "old", SPEC 2, (char **)NULL,
- X "orig-to-include-mask", INT 0, (char **)&orig_to_include_mask,
- X "overlap", INT 0, (char **)&overlap,
- X "pager", STR SAFE 3, (char **)&pager,
- X "patch-command", STR SAFE 1, (char **)patch_command,
- X "preview-continuation", INT 0, (char **)&preview_continuation,
- X "preview-mark-read", BOOL 0, (char **)&preview_mark_read,
- X "printer", STR SAFE 1, (char **)printer,
- X "query-signature", BOOL 0, (char **)&query_signature,
- X "quick-count", BOOL 0, (char **)&quick_unread_count,
- X "quick-save", BOOL 0, (char **)&quick_save,
- X "re-layout", INT 0, (char **)&re_layout,
- X "record", SPEC 1, (char **)NULL,
- X "repeat", BOOL 0, (char **)&fmt_rptsubj,
- X "repeat-group-query", BOOL 0, (char **)&repeat_group_query,
- X "report-cost", BOOL 0, (char **)&report_cost_on_exit,
- X "response-check-pause", INT 0, (char **)&response_check_pause,
- X "response-default-answer", STR 0, (char **)&response_dflt_answer,
- X "retain-seen-status", BOOL 0, (char **)&retain_seen_status,
- X "retry-on-error", INT 0, (char **)&retry_on_error,
- X "save-counter", STR 3, (char **)&save_counter_format,
- X "save-counter-offset", INT 0, (char **)&save_counter_offset,
- X "save-report", BOOL 0, (char **)&save_report,
- X "scroll-clear-page", BOOL 0, (char **)&scroll_clear_page,
- X "select-leave-next", BOOL 0, (char **)&select_leave_next,
- X "select-on-sender", BOOL 0, (char **)&select_on_sender,
- X "shell", STR SAFE 0, (char **)&user_shell,
- X "shell-restrictions", BOOL INIT 0, (char **)&shell_restrictions,
- X "silent", BOOL 0, (char **)&silent,
- X "slow-mode", BOOL 0, (char **)&slow_mode,
- X "slow-speed", INT 0, (char **)&slow_speed,
- X "sort", BOOL 2, (char **)&dont_sort_articles,
- X "sort-mode", INT 0, (char **)&sort_mode,
- X "spell-checker", STR 0, (char **)&spell_checker,
- X "split", BOOL 4, (char **)&dont_split_digests,
- X "stop", INT 0, (char **)&first_page_lines,
- X "subject-match-limit", INT 0, (char **)&subject_match_limit,
- X "subject-match-offset", INT 0, (char **)&match_skip_prefix,
- X "subject-match-parts", BOOL 0, (char **)&match_parts_equal,
- X "suggest-default-save", BOOL 0, (char **)&suggest_save_file,
- X "tidy-newsrc", BOOL 0, (char **)&tidy_newsrc,
- X "time", BOOL 0, (char **)&show_current_time,
- X "unshar-command", STR SAFE 1, (char **)unshar_command,
- X "unshar-header-file", STR 0, (char **)&unshar_header_file,
- X "unsubscribe-mark-read", BOOL 4, (char **)&keep_unsub_long,
- X "update-frequency", INT 0, (char **)&newsrc_update_freq,
- X "use-selections", BOOL 0, (char **)&use_selections,
- X "visible-bell", BOOL 0, (char **)&use_visible_bell,
- X "window", INT 1, (char **)&preview_window,
- X "word-key", KEY 0, (char **)&delword_key,
- X "wrap-header-margin", INT 2, (char **)&wrap_headers
- X};
- X
- X#define TABLE_SIZE (sizeof(variables)/sizeof(struct variable_defs))
- X
- X#define INT_VAR (*((int *)(var->var_addr)))
- X#define BOOL_VAR (*((int *)(var->var_addr)))
- X#define STR_VAR (*(var->var_addr))
- X#define CBUF_VAR ((char *)(var->var_addr))
- X#define KEY_VAR (*((key_type *)(var->var_addr)))
- X
- X#define VAR_TYPE (var->var_flags & 0x7000)
- X#define VAR_OP (var->var_flags & 0x000f)
- X
- Xstatic struct variable_defs *lookup_variable(variable)
- Xchar *variable;
- X{
- X register struct variable_defs *var;
- X register i, j, k, t;
- X
- X i = 0; j = TABLE_SIZE - 1;
- X
- X while (i <= j) {
- X k = (i + j) / 2;
- X var = &variables[k];
- X
- X if ( (t=strcmp(variable, var->var_name)) > 0)
- X i = k+1;
- X else
- X if (t < 0)
- X j = k-1;
- X else
- X return var;
- X }
- X
- X init_message("unknown variable: %s", variable);
- X return NULL;
- X}
- X
- X
- Xstatic adjust(str)
- Xregister char *str;
- X{
- X if (str == NULL) return;
- X while (*str && !isspace(*str) && *str != '#') str++;
- X *str = NUL;
- X}
- X
- Xset_variable(variable, on, val_string)
- Xchar *variable;
- Xint on;
- Xchar *val_string;
- X{
- X int value;
- X register struct variable_defs *var;
- X
- X if (strncmp(variable, "no", 2) == 0) {
- X on = !on;
- X variable += 2;
- X if (variable[0] == '-') variable++;
- X }
- X
- X if ((var = lookup_variable(variable)) == NULL)
- X return 0;
- X
- X if (!in_init && (var->var_flags & (V_INIT | V_SAFE))) {
- X if (var->var_flags & V_INIT) {
- X msg("'%s' can only be set in the init file", variable);
- X return 0;
- X }
- X if (shell_restrictions) {
- X msg("Restricted operation - cannot change");
- X return 0;
- X }
- X }
- X
- X if (!on || val_string == NULL)
- X value = 0;
- X else
- X value = atoi(val_string);
- X
- X var->var_flags |= V_MODIFIED;
- X
- X switch (VAR_TYPE) {
- X
- X case V_STRING:
- X
- X switch (VAR_OP) {
- X case 0:
- X STR_VAR = (on && val_string) ? copy_str(val_string) : (char *)NULL;
- X break;
- X
- X case 1:
- X strcpy(CBUF_VAR, (on && val_string) ? val_string : "");
- X break;
- X
- X case 2:
- X if (on) {
- X char exp_buf[FILENAME];
- X
- X adjust(val_string);
- X if (val_string) {
- X if (expand_file_name(exp_buf, val_string, 1))
- X STR_VAR = home_relative(exp_buf);
- X }
- X } else
- X STR_VAR = (char *)NULL;
- X break;
- X
- X case 3:
- X if (!on || val_string == NULL) {
- X msg("Cannot unset string `%s'", variable);
- X break;
- X }
- X STR_VAR = copy_str(val_string);
- X break;
- X }
- X break;
- X
- X case V_BOOLEAN:
- X
- X if (val_string)
- X if (val_string[0] == 'o')
- X on = val_string[1] == 'n'; /* on */
- X else
- X on = val_string[0] == 't'; /* true */
- X
- X switch (VAR_OP) {
- X case 0:
- X BOOL_VAR = on;
- X break;
- X
- X case 1:
- X BOOL_VAR = on;
- X return 1;
- X
- X case 2:
- X if (BOOL_VAR == on) {
- X BOOL_VAR = !on;
- X if (!in_init) {
- X sort_articles(BOOL_VAR ? 0 : -1);
- X return 1;
- X }
- X }
- X break;
- X
- X case 4:
- X BOOL_VAR = !on;
- X break;
- X }
- X break;
- X
- X case V_INTEGER:
- X
- X switch (VAR_OP) {
- X case 0:
- X case 1:
- X INT_VAR = value;
- X break;
- X
- X case 2:
- X case 3:
- X if (!on) value = -1;
- X INT_VAR = value;
- X break;
- X }
- X return (VAR_OP & 1);
- X
- X case V_KEY:
- X switch (VAR_OP) {
- X case 0:
- X if (val_string) {
- X if (*val_string) adjust(val_string + 1); /* #N is valid */
- X KEY_VAR = parse_key(val_string);
- X }
- X break;
- X }
- X break;
- X
- X case V_SPECIAL:
- X
- X switch (VAR_OP) {
- X case 1:
- X if (val_string) {
- X adjust(val_string);
- X news_record = home_relative(val_string);
- X mail_record = news_record;
- X }
- X break;
- X
- X case 2:
- X also_read_articles = on;
- X article_limit = (on && value > 0) ? value : -1;
- X break;
- X }
- X break;
- X }
- X return 0;
- X}
- X
- Xtoggle_variable(variable)
- Xchar *variable;
- X{
- X register struct variable_defs *var;
- X
- X if ((var = lookup_variable(variable)) == NULL) return;
- X if (VAR_TYPE != V_BOOLEAN) {
- X init_message("variable %s is not boolean", variable);
- X return;
- X }
- X
- X BOOL_VAR = !BOOL_VAR;
- X}
- X
- X
- Xtest_variable(expr)
- Xchar *expr;
- X{
- X char *variable;
- X register struct variable_defs *var;
- X int res = -1;
- X
- X variable = expr;
- X if ((expr = strchr(variable, '=')) == NULL)
- X goto err;
- X
- X *expr++ = NUL;
- X
- X if ((var = lookup_variable(variable)) == NULL) {
- X msg("testing unknown variable %s=%s", variable, expr);
- X goto out;
- X }
- X
- X switch (VAR_TYPE) {
- X
- X case V_BOOLEAN:
- X res = BOOL_VAR;
- X
- X if (strcmp(expr, "on") == 0 || strcmp(expr, "true") == 0) break;
- X if (strcmp(expr, "off") == 0 || strcmp(expr, "false") == 0) {
- X res = !res;
- X break;
- X }
- X msg("boolean variables must be tested =on or =off");
- X break;
- X
- X case V_INTEGER:
- X res = (INT_VAR == atoi(expr)) ? 1 : 0;
- X break;
- X
- X default:
- X msg("%s: cannot only test boolean and integer variables", variable);
- X break;
- X }
- X out:
- X *--expr = '=';
- X err:
- X return res;
- X}
- X
- X
- Xvar_completion(path, index)
- Xchar *path;
- Xint index;
- X{
- X static char *head, *tail = NULL;
- X static int len;
- X static struct variable_defs *var, *help_var;
- X
- X if (index < 0) return 0;
- X
- X if (path) {
- X head = path;
- X tail = path + index;
- X while (*head && isspace(*head)) head++;
- X if (strncmp(head, "no", 2) == 0) {
- X head += 2;
- X if (*head == '-') head++;
- X }
- X
- X help_var = var = variables;
- X len = tail - head;
- X
- X return 1;
- X }
- X
- X if (index) {
- X list_completion((char *)NULL);
- X
- X for (;; help_var++) {
- X if (help_var >= &variables[TABLE_SIZE]) {
- X help_var = variables;
- X break;
- X }
- X
- X index = strncmp(help_var->var_name, head, len);
- X if (index < 0) continue;
- X if (index > 0) {
- X help_var = variables;
- X break;
- X }
- X if (list_completion(help_var->var_name) == 0) break;
- X }
- X fl;
- X return 1;
- X }
- X
- X for (; var < &variables[TABLE_SIZE]; var++) {
- X if (len == 0)
- X index = 0;
- X else
- X index = strncmp(var->var_name, head, len);
- X if (index < 0) continue;
- X if (index > 0) break;
- X sprintf(tail, "%s ", var->var_name + len);
- X var++;
- X return 1;
- X }
- X return 0;
- X}
- X
- Xstatic struct var_stack {
- X struct var_stack *next;
- X struct variable_defs *v;
- X int mod_flag;
- X union {
- X int ivar;
- X int bool;
- X char key;
- X char *str;
- X } value;
- X} *var_stack = NULL, *vs_pool = NULL;
- X
- Xmark_var_stack()
- X{
- X register struct var_stack *vs;
- X
- X if (vs_pool) {
- X vs = vs_pool;
- X vs_pool = vs->next;
- X } else
- X vs = newobj(struct var_stack, 1);
- X
- X vs->next = var_stack;
- X var_stack = vs;
- X vs->v = NULL;
- X}
- X
- Xpush_variable(variable)
- Xchar *variable;
- X{
- X register struct variable_defs *var;
- X register struct var_stack *vs;
- X
- X if (strncmp(variable, "no", 2) == 0) {
- X variable += 2;
- X if (variable[0] == '-') variable++;
- X }
- X
- X if ((var = lookup_variable(variable)) == NULL) {
- X msg("pushing unknown variable %s", variable);
- X return 0;
- X }
- X
- X mark_var_stack();
- X vs = var_stack;
- X vs->v = var;
- X vs->mod_flag = var->var_flags & V_MODIFIED;
- X
- X switch (VAR_TYPE) {
- X
- X case V_STRING:
- X
- X switch (VAR_OP) {
- X case 0: /* if we update one of these variables, */
- X case 2: /* new storage will be allocated for it */
- X case 3: /* so it is ok just to save the pointer */
- X vs->value.str = STR_VAR;
- X break;
- X
- X case 1: /* we free this memory when restored */
- X vs->value.str = copy_str(CBUF_VAR);
- X break;
- X }
- X break;
- X
- X case V_BOOLEAN:
- X vs->value.bool = BOOL_VAR;
- X break;
- X
- X case V_INTEGER:
- X vs->value.ivar = INT_VAR;
- X break;
- X
- X case V_KEY:
- X vs->value.key = KEY_VAR;
- X break;
- X
- X case V_SPECIAL:
- X msg("Cannot push pseudo variable %s", var->var_name);
- X break;
- X }
- X
- X return 1;
- X}
- X
- Xrestore_variables()
- X{
- X register struct variable_defs *var;
- X register struct var_stack *vs, *vs1;
- X
- X vs = var_stack;
- X
- X while (vs != NULL) {
- X if ((var = vs->v) == NULL) {
- X var_stack = vs->next;
- X vs->next = vs_pool;
- X vs_pool = vs;
- X return;
- X }
- X
- X var->var_flags &= ~V_MODIFIED;
- X var->var_flags |= vs->mod_flag;
- X
- X switch (VAR_TYPE) {
- X
- X case V_STRING:
- X switch (VAR_OP) {
- X case 0: /* only restore the string if changed; then we */
- X case 2: /* can also free the memory occupied by the */
- X case 3: /* 'new' value (if not NULL) */
- X if (STR_VAR != vs->value.str) {
- X if (STR_VAR != NULL) freeobj(STR_VAR);
- X STR_VAR = vs->value.str;
- X }
- X break;
- X
- X case 1: /* it fitted before, so it will fit againg */
- X strcpy(CBUF_VAR, vs->value.str);
- X freeobj(vs->value.str);
- X break;
- X }
- X break;
- X
- X case V_BOOLEAN:
- X BOOL_VAR = vs->value.bool;
- X break;
- X
- X case V_INTEGER:
- X INT_VAR = vs->value.ivar;
- X break;
- X
- X case V_KEY:
- X KEY_VAR = vs->value.key;
- X break;
- X
- X case V_SPECIAL: /* these are not saved, so... */
- X break;
- X }
- X
- X vs1 = vs->next;
- X vs->next = vs_pool;
- X vs_pool = vs;
- X vs = vs1;
- X }
- X var_stack = NULL;
- X}
- X
- Xstatic var_on_stack(var)
- Xregister struct variable_defs *var;
- X{
- X register struct var_stack *vs;
- X
- X for (vs = var_stack; vs; vs = vs->next)
- X if (vs->v == var) return 1;
- X return 0;
- X}
- X
- Xdisp_variables(all)
- Xint all;
- X{
- X char *str, pushed;
- X int b;
- X register struct variable_defs *var;
- X
- X if (in_init) return;
- X
- X pg_init(0, 1);
- X
- X clrdisp();
- X if (novice && !all) {
- X msg("Use `:set all' to see all variable settings");
- X home();
- X }
- X pg_next();
- X so_printf("\1Variable settings:\1");
- X
- X for (var = variables; var < &variables[TABLE_SIZE]; var++) {
- X pushed =
- X var_on_stack(var) ? '>' :
- X (var->var_flags & V_MODIFIED) ? '*' : ' ';
- X
- X if (!all && pushed == ' ') continue;
- X
- X switch (VAR_TYPE) {
- X case V_STRING:
- X if (pg_next() < 0) goto out;
- X str = (VAR_OP == 1) ? CBUF_VAR : STR_VAR;
- X if (str == NULL) str = "";
- X printf("%c %-20.20s = \"%s\"\n", pushed, var->var_name, str);
- X break;
- X
- X case V_BOOLEAN:
- X if (pg_next() < 0) goto out;
- X b = BOOL_VAR;
- X if (VAR_OP == 2 || VAR_OP == 4) b = !b;
- X printf("%c %-20.20s = %s\n",
- X pushed, var->var_name, b ? "on" : "off");
- X break;
- X
- X case V_INTEGER:
- X if (pg_next() < 0) goto out;
- X printf("%c %-20.20s = %d\n", pushed, var->var_name, INT_VAR);
- X break;
- X
- X case V_KEY:
- X if (pg_next() < 0) goto out;
- X printf("%c %-20.20s = %s\n",
- X pushed, var->var_name, key_name(KEY_VAR));
- X break;
- X
- X case V_SPECIAL:
- X switch (VAR_OP) {
- X case 1:
- X break;
- X case 2:
- X if (also_read_articles) {
- X if (pg_next() < 0) goto out;
- X printf("%c %-20.20s = %d\n",
- X pushed, var->var_name, article_limit);
- X }
- X break;
- X }
- X break;
- X }
- X }
- X
- Xout:
- X pg_end();
- X}
- END_OF_FILE
- if test 20923 -ne `wc -c <'variable.c'`; then
- echo shar: \"'variable.c'\" unpacked with wrong size!
- fi
- # end of 'variable.c'
- fi
- echo shar: End of archive 12 \(of 22\).
- cp /dev/null ark12isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 22 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
-
- exit 0 # Just in case...
-